#ifndef __MAP2_H__
#define __MAP2_H__

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdio.h>
#include <stdint.h>
    /* MurmurHash2, by Austin Appleby
     * Note - This code makes a few assumptions about how your machine behaves -
     * 1. We can read a 4-byte value from any address without crashing
     * 2. sizeof(int) == 4
     *
     * And it has a few limitations -
     *
     * 1. It will not work incrementally.
     * 2. It will not produce the same results on little-endian and big-endian
     *    machines.
     */
    static unsigned int map_murmur_hash(const void *key, uint32_t len)
    {
        /* 'm' and 'r' are mixing constants generated offline.
         They're not really 'magic', they just happen to work well.  */
        uint32_t seed = 5381;
        const uint32_t m = 0x5bd1e995;
        const int r = 24;

        /* Initialize the hash to a 'random' value */
        uint32_t h = seed ^ len;

        /* Mix 4 bytes at a time into the hash */
        const unsigned char *data = (const unsigned char *)key;

        while (len >= 4)
        {
            uint32_t k = *(uint32_t *)data;

            k *= m;
            k ^= k >> r;
            k *= m;

            h *= m;
            h ^= k;

            data += 4;
            len -= 4;
        }

        /* Handle the last few bytes of the input array  */
        switch (len)
        {
        case 3:
            h ^= data[2] << 16;
        case 2:
            h ^= data[1] << 8;
        case 1:
            h ^= data[0];
            h *= m;
        };

        /* Do a few final mixes of the hash to ensure the last few
         * bytes are well-incorporated. */
        h ^= h >> 13;
        h *= m;
        h ^= h >> 15;

        return (unsigned int)h;
    }

    /* Thomas Wang's 32 bit Mix Function
     * 包转一层用于适配 map_hash_impl
     */
    static unsigned int map_u32_hash(unsigned int key, uint32_t len)
    {
        key += ~(key << 15);
        key ^= (key >> 10);
        key += (key << 3);
        key ^= (key >> 6);
        key += ~(key << 11);
        key ^= (key >> 16);
        return key;
    }

    typedef void *(*map_malloc_impl)(size_t size);
    typedef void (*map_free_impl)(void *addr);
    // 计算hash的数据
    typedef uint32_t (*map_hash_impl)(const void *key, const uint32_t len);
    // 判断key1(map中的key)与key2(用户调用函数传入的key)是否相等
    typedef int (*map_equal_impl)(const void *key1, const void *key2);
    // 释放键值对结构体内存前调用的函数
    typedef void (*map_deinit_before_impl)(const void *key, const void *value);
    // 遍历键值对 值可以被替换或释放
    typedef int (*map_foreach_impl)(const void *key, void *value, void *userdata);

    // 隐藏map_entry_t 内部数据
    typedef struct map_entry_st map_entry_t;
    typedef struct map_st
    {
        map_hash_impl hash_fn;
        map_equal_impl equal_fn;
        map_deinit_before_impl deinit_before_fn;
        // 数据桶数组
        map_entry_t **entrys[2];
        // 已使用节点
        uint32_t used;
        // 数据容器总容量
        uint32_t cap;
        // 扩容进度(非扩容状态时为0，扩容时最大值为cap)
        uint32_t rfidx;
    } map_t;
    
    extern void map_memctl_set(map_malloc_impl map_malloc_func, map_free_impl map_free_func);
    extern void map_init(map_t *map, map_hash_impl hash_fn, map_equal_impl equal_fn, map_deinit_before_impl deinit_before_fn);
    extern void map_init1(map_t *map, uint32_t cap, map_hash_impl hash_fn, map_equal_impl equal_fn, map_deinit_before_impl deinit_before_fn);
    extern void map_deinit(map_t *map);
    extern int8_t map_put(map_t *map, void *key, uint32_t keylen, void *value);
    extern int8_t map_upt(map_t *map, void *key, uint32_t keylen, void *value);
    extern void *map_get(map_t *map, void *key, uint32_t keylen);
    extern int8_t map_del(map_t *map, void *key, uint32_t keylen);
    extern int64_t map_foreach(map_t *map, map_foreach_impl foreach_fn, void *userdata);
    extern void map_used(map_t *map);
    extern char map_enlarging_forced(map_t *map, size_t count);
    extern char map_enlarging_forced2(map_t *map, long long ms);
#ifdef __cplusplus
}
#endif

#endif